package com.globallogic.javatrainings.sergiiivanov.model;

/**
 * Takes {@link ScoreRecord} collection and provides print-ready reports<br>
 * <b>Usage:</b><br>
 * <ol>
 * <li>{@link #setScoresCollection(MyArray)}
 * <li>{@link #setFilterCourse(Course)} - optional
 * <li>{@link #setFilterTeacher(Teacher)} - optional
 * <li>{@link #getTable()}
 * <li>{@link #getAveragesDiscipline()}
 * </ol>
 * 
 * @author Sergey
 * 
 */
public class ScoresProcessor {
    private MyArray<ScoreRecord> scores;
    private Course courceFilter;
    private Teacher teacherFilter;

    /**
     * sets {@link ScoreRecord} collection
     * 
     * @param s
     *            {@link MyArray} of {@link ScoreRecord}
     */
    public void setScoresCollection(MyArray<ScoreRecord> s) {
        scores = s.copy();
    }

    /**
     * Sets filtering by {@link Course}. If <b>null</b> - does not filter
     * 
     * @param c
     *            {@link Course} to filter results by
     */
    public void setFilterCourse(Course c) {
        courceFilter = c;
    }

    /**
     * Sets filtering by {@link Teacher}. If <b>null</b> - does not filter
     * 
     * @param t
     *            {@link Teacher} to filter results by
     */
    public void setFilterTeacher(Teacher t) {
        teacherFilter = t;
    }

    /**
     * @return {@link MyArray} of {@link ScoreRecord} <br>
     *         collection, that was set by {@link #setScoresCollection(MyArray)}
     *         , but now filtered with {@link #setFilterCourse(Course)} and
     *         {@link #setFilterTeacher(Teacher)}
     */
    public MyArray<ScoreRecord> getFilteredList() {
        MyArray<ScoreRecord> result = new MyArray<ScoreRecord>();
        for (ScoreRecord sr : scores) {
            if (courceFilter != null) {
                if (sr.getCourse() != null && !sr.getCourse().equals(courceFilter))
                    continue;
                if (sr.getCourse() == null && sr.courseName != null && !sr.courseName.equals(courceFilter.getName()))
                    continue;
            }
            if (teacherFilter != null) {
                if (sr.getTeacher() != null && !sr.getTeacher().equals(teacherFilter))
                    continue;
                if (sr.getTeacher() == null && sr.teacherName != null && !sr.teacherName.equals(teacherFilter.getName()))
                    continue;
            }
            result.add(sr);
        }
        return result;
    }

    /**
     * @return print-ready table as String[][]
     */
    public String[][] getTable() {
        MyArray<String[]> results = new MyArray<String[]>(new String[0][0]);
        for (ScoreRecord sr : getFilteredList()) {
            MyArray<String> line = new MyArray<String>(new String[0]);
            line.add(sr.courseName);
            line.add(sr.lectureName);
            line.add(Integer.toString(sr.score));
            line.add(sr.scoreReason);
            line.add(sr.teacherName);
            results.add(line.toArray());
        }
        return results.toArray();
    }

    /**
     * calculates averages by discipline
     * 
     * @return print-ready table of average scores as String[][]
     * @throws UniversityWarning
     *             should not return until MyMap is not broken
     * @throws UniversityFailure
     *             application crash
     */
    public String[][] getAveragesDiscipline() throws UniversityFailure, UniversityWarning {
        MyMap<Integer> count = new MyMap<Integer>();
        MyMap<Integer> sum = new MyMap<Integer>();
        for (ScoreRecord scoreRecord : getFilteredList()) {
            String disciplineName = scoreRecord.discipline.getRepresentation();
            try {
                count.get(disciplineName);
                sum.get(disciplineName);
            } catch (Exception e) {
                count.set(disciplineName, 0);
                sum.set(disciplineName, 0);
            }
            count.set(disciplineName, count.get(disciplineName) + 1);
            sum.set(disciplineName, sum.get(disciplineName) + scoreRecord.score);
        }
        String[] keys = count.getKeys();
        String[][] result = new String[keys.length][2];
        for (int i = 0; i < keys.length; i++) {
            result[i][0] = keys[i];
            result[i][1] = Double.toString(((double) sum.get(keys[i]) / count.get(keys[i])));
        }
        return result;
    }
}
